import {Choice, M698pdu} from "./M698pdu";
import {FjCAPdu} from "./FjCAPdu";
import {Buffer} from "buffer";
import {ReverseByteArrayOutputStream} from "../ReverseByteArrayOutputStream";
import {FjSApdu} from "./FjSApdu";
import {ReverseByteArrayInputStream} from "../ReverseByteArrayInputStream";


export class Apdu {


    m698pdu: M698pdu | null = null;
    fjcliapdu: FjCAPdu | null = null;
    fjsrvapdu: FjSApdu | null = null;
    static instance = null;

    static getInstance() : Apdu{
        if(this.instance == null){
            this.instance = new Apdu(M698pdu.getInstance());
        }
        return this.instance;
    }

    getFjsrvapdu() : FjSApdu{
        if(this.fjsrvapdu != null){
            return this.fjsrvapdu;
        }else {
            throw new Error("fjsrvapdu is null");
        }
    }

    setFjsrvapdu(fjsrvapdu : FjSApdu){
        this.fjsrvapdu = fjsrvapdu;
    }

    getFjcliapdu(): FjCAPdu {
        if(this.fjcliapdu != null){
            return this.fjcliapdu;
        }else {
            throw new Error("fjcliapdu is null");
        }
    }

    setFjcliapdu(fjcliapdu: FjCAPdu) {
        this.fjcliapdu = fjcliapdu;
    }

    constructor(m698pdu: M698pdu) {
        this.m698pdu = m698pdu;
    }

    getCosemPdu() : M698pdu{
        if(this.m698pdu != null){
            return this.m698pdu;
        }else{
            throw new Error("698pdu is null");
        }
    }

    decode(bytes : Buffer) : Apdu{
        let is = new ReverseByteArrayInputStream(bytes);
        let size = is.available();
        let m698pdu = new M698pdu();
        let aPdu = new Apdu(m698pdu);
        if (size > 0) {
            aPdu.m698pdu.decode(is);
            console.log(aPdu.m698pdu.toString());
            //fj data
            if (aPdu.m698pdu.getChoiceIndex() == Choice.GET_REQUEST
                || aPdu.m698pdu.getChoiceIndex() == Choice.SET_REQUEST
                || aPdu.m698pdu.getChoiceIndex() == Choice.ACTION_REQUEST
                || aPdu.m698pdu.getChoiceIndex() == Choice.CONNECT_REQUEST
                || aPdu.m698pdu.getChoiceIndex() == Choice.PROXY_REQUEST) {
                aPdu.fjcliapdu = new FjCAPdu();
                aPdu.fjcliapdu.decode(is);
            } else if (aPdu.m698pdu.getChoiceIndex() == Choice.GET_RESPONSE
                || aPdu.m698pdu.getChoiceIndex() == Choice.SET_RESPONSE
                || aPdu.m698pdu.getChoiceIndex() == Choice.ACTION_RESPONSE
                || aPdu.m698pdu.getChoiceIndex() == Choice.CONNECT_RESPONSE
                || aPdu.m698pdu.getChoiceIndex() == Choice.PROXY_RESPONSE) {
                aPdu.fjsrvapdu = new FjSApdu();
                aPdu.fjsrvapdu.decode(is);
            }
        }
        return aPdu;
    }

    encode(buffer : Buffer) : number{
        let baos = new ReverseByteArrayOutputStream();
        baos.setBuf_Index(buffer, buffer.length - 1);
        return this.encodeCosemPdu(buffer, baos);
    }

    encodeCosemPdu(buffer : Buffer, baos : ReverseByteArrayOutputStream) : number{
        let ret = 0;
        if (this.m698pdu != null) {
            if (this.m698pdu.getChoiceIndex() == Choice.GET_REQUEST
                || this.m698pdu.getChoiceIndex() == Choice.SET_REQUEST
                || this.m698pdu.getChoiceIndex() == Choice.ACTION_REQUEST
                || this.m698pdu.getChoiceIndex() == Choice.CONNECT_REQUEST
                || this.m698pdu.getChoiceIndex() == Choice.PROXY_REQUEST) {
                if (this.fjcliapdu == null)
                    this.fjcliapdu = new FjCAPdu();
                ret += this.fjcliapdu.encode(baos);
            }else if(this.m698pdu.getChoiceIndex() == Choice.GET_RESPONSE
                || this.m698pdu.getChoiceIndex() == Choice.SET_RESPONSE
                || this.m698pdu.getChoiceIndex() == Choice.ACTION_RESPONSE
                || this.m698pdu.getChoiceIndex() == Choice.CONNECT_RESPONSE
                || this.m698pdu.getChoiceIndex() == Choice.PROXY_RESPONSE){
                if (this.fjsrvapdu == null)
                    this.fjsrvapdu = new FjSApdu();
                ret += this.fjsrvapdu.encode(baos);
            }
        }
        ret += (this.m698pdu == null ? 0 : this.m698pdu.encode(baos));
        console.log("ret" + ret);
        return ret;
    }

    toString() : string{
        if(this.m698pdu != null){
            return "APDU:" + this.m698pdu;
        }else{
            return "APDU: is null";
        }
    }

}
